home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / ge_cool.lha / GE_COOL2.1 / cpp / cpp4.c.original < prev    next >
Text File  |  1992-04-13  |  18KB  |  628 lines

  1. /*
  2.  
  3.  
  4.  Copyright (C) 1990 Texas Instruments Incorporated.
  5.  
  6.  Permission is granted to any individual or institution to use, copy, modify,
  7.  and distribute this software, provided that this complete copyright and
  8.  permission notice is maintained, intact, in all copies and supporting
  9.  documentation.
  10.  
  11.  Texas Instruments Incorporated provides this software "as is" without
  12.  express or implied warranty.
  13.  
  14.  
  15.  *                C P P 4 . C
  16.  *        M a c r o  D e f i n i t i o n s
  17.  *
  18.  * Edit History
  19.  * 30-Oct-90    MJF    Fix __LINE__ when in a macro
  20.  * 31-Aug-84    MM    USENET net.sources release
  21.  * 04-Oct-84    MM    __LINE__ and __FILE__ must call ungetstring()
  22.  *            so they work correctly with token concatenation.
  23.  *            Added string formal recognition.
  24.  * 25-Oct-84    MM    "Short-circuit" evaluate #if's so that we
  25.  *            don't print unnecessary error messages for
  26.  *            #if !defined(FOO) && FOO != 0 && 10 / FOO ...
  27.  * 31-Oct-84    ado/MM    Added token concatenation
  28.  *  6-Nov-84    MM    Split off eval stuff
  29.  * 21-Oct-85    RMS    Rename `token' to `tokenbuf'.
  30.  *            In doundef, don't complain if arg already not defined.
  31.  * 20-Apr-90    MJF     Changed redefining of defined variable to a warning
  32.  * 18-May-90    MBN     Conditional compilation for COOL to get "clean" cpp
  33.  * 25-Jun-91    GPD    Fixes to make ## operator expansion ANSI conformant.
  34.  */
  35.  
  36. #include    <stdio.h>
  37. #include    <ctype.h>
  38. #include    "cppdef.h"
  39. #include    "cpp.h"
  40. /*
  41.  * parm[], parmp, and parlist[] are used to store #define() argument
  42.  * lists.  nargs contains the actual number of parameters stored.
  43.  */
  44. static char    parm[NPARMWORK + 1];    /* define param work buffer     */
  45. static char    *parmp;            /* Free space in parm        */
  46. static char    *parlist[LASTPARM];    /* -> start of each parameter    */
  47. static int    nargs;            /* Parameters for this macro    */
  48.  
  49. dodefine()
  50. /*
  51.  * Called from control when a #define is scanned.  This module
  52.  * parses formal parameters and the replacement string.  When
  53.  * the formal parameter name is encountered in the replacement
  54.  * string, it is replaced by a character in the range 128 to
  55.  * 128+NPARAM (this allows up to 32 parameters within the
  56.  * Dec Multinational range).  If cpp is ported to an EBCDIC
  57.  * machine, you will have to make other arrangements.
  58.  *
  59.  * There is some special case code to distinguish
  60.  *    #define foo    bar
  61.  * from    #define foo()    bar
  62.  *
  63.  * Also, we make sure that
  64.  *    #define    foo    foo
  65.  * expands to "foo" but doesn't put cpp into an infinite loop.
  66.  *
  67.  * A warning message is printed if you redefine a symbol to a
  68.  * different text.  I.e,
  69.  *    #define    foo    123
  70.  *    #define foo    123
  71.  * is ok, but
  72.  *    #define foo    123
  73.  *    #define    foo    +123
  74.  * is not.
  75.  *
  76.  * The following subroutines are called from define():
  77.  * checkparm    called when a token is scanned.  It checks through the
  78.  *        array of formal parameters.  If a match is found, the
  79.  *        token is replaced by a control byte which will be used
  80.  *        to locate the parameter when the macro is expanded.
  81.  * textput    puts a string in the macro work area (parm[]), updating
  82.  *        parmp to point to the first free byte in parm[].
  83.  *        textput() tests for work buffer overflow.
  84.  * charput    puts a single character in the macro work area (parm[])
  85.  *        in a manner analogous to textput().
  86.  */
  87. {
  88.     register int        c;
  89.     register DEFBUF        *dp;        /* -> new definition    */
  90.     int            isredefine;    /* TRUE if redefined    */
  91.     char            *old;        /* Remember redefined    */
  92.     extern int        save();        /* Save char in work[]    */
  93.  
  94.     if (type[(c = skipws())] != LET)
  95.         goto bad_define;
  96.     isredefine = FALSE;            /* Set if redefining    */
  97.     if ((dp = lookid(c)) == NULL)        /* If not known now    */
  98.         dp = defendel(tokenbuf, FALSE);    /* Save the name    */
  99.     else {                    /* It's known:        */
  100.         isredefine = TRUE;            /* Remember this fact    */
  101.         old = dp->repl;            /* Remember replacement    */
  102.         dp->repl = NULL;            /* No replacement now    */
  103.     }
  104.     parlist[0] = parmp = parm;        /* Setup parm buffer    */
  105.     if ((c = get()) == '(') {        /* With arguments?    */
  106.         nargs = 0;                /* Init formals counter    */
  107.         do {                /* Collect formal parms    */
  108.         if (nargs >= LASTPARM)
  109.             cfatal("Too many arguments for macro", NULLST);
  110.         else if ((c = skipws()) == ')')
  111.             break;            /* Got them all        */
  112.         else if (type[c] != LET)    /* Bad formal syntax    */
  113.             goto bad_define;
  114.         scanid(c);            /* Get the formal param    */
  115.         parlist[nargs++] = parmp;    /* Save its start    */
  116.         textput(tokenbuf);        /* Save text in parm[]    */
  117.         } while ((c = skipws()) == ',');    /* Get another argument    */
  118.         if (c != ')')            /* Must end at )    */
  119.         goto bad_define;
  120.         c = ' ';                /* Will skip to body    */
  121.     }
  122.     else {
  123.         /*
  124.          * DEF_NOARGS is needed to distinguish between
  125.          * "#define foo" and "#define foo()".
  126.          */
  127.         nargs = DEF_NOARGS;            /* No () parameters    */
  128.     }
  129.     if (type[c] == SPA)            /* At whitespace?    */
  130.         c = skipws();            /* Not any more.    */
  131.     workp = work;                /* Replacement put here    */
  132.     inmacro = TRUE;                /* Keep \<newline> now    */
  133.     while (c != EOF_CHAR && c != '\n') {    /* Compile macro body    */
  134. #if OK_CONCAT
  135.         if (c == '#') {            /* Token concatenation?    */
  136.           if((c = get()) != '#') {
  137.         save('#');            /* Lone #, just save it. */
  138.         if(type[c] == LET) {
  139.           if (checkparm(c, dp))     /* Single # next to parm */
  140.             workp[-2] = MAC_PARM + PAR_MAC;/* Mark next parameter */
  141.           c = get();}  
  142.             continue;}
  143.           while (workp > work && type[(unsigned char)workp[-1]] == SPA)
  144.         --workp;            /* Erase leading spaces    */
  145.           /* save(TOK_SEP); */        /* Stuff a delimiter    */
  146.           c = skipws();            /* Eat whitespace    */
  147.           continue;
  148.         }
  149. #endif    /*  OK_CONCAT  */
  150.         switch (type[c]) {
  151.         case LET:
  152.         checkparm(c, dp);        /* Might be a formal    */
  153.         break;
  154.  
  155.         case DIG:                /* Number in mac. body    */
  156.         case DOT:                /* Maybe a float number    */
  157.         scannumber(c, save);        /* Scan it off        */
  158.         break;
  159.  
  160.         case QUO:                /* String in mac. body    */
  161. #if STRING_FORMAL
  162.         stparmscan(c, dp);        /* Do string magic    */
  163. #else
  164.         scanstring(c, save);
  165. #endif
  166.         break;
  167.  
  168.         case BSH:                /* Backslash        */
  169.         save('\\');
  170.         if ((c = get()) == '\n')
  171.             wrongline = TRUE;
  172.         save(c);
  173.         break;
  174.  
  175.         case SPA:                /* Absorb whitespace    */
  176.         /*
  177.          * Note: the "end of comment" marker is passed on
  178.          * to allow comments to separate tokens.
  179.          */
  180.         if (workp[-1] == ' ')        /* Absorb multiple    */
  181.             break;            /* spaces        */
  182.         else if (c == '\t')
  183.             c = ' ';            /* Normalize tabs    */
  184.         /* Fall through to store character            */
  185.         default:                /* Other character    */
  186.         save(c);
  187.         break;
  188.         }
  189.         c = get();
  190.     }
  191.     inmacro = FALSE;            /* Stop newline hack    */
  192.     unget();                /* For control check    */
  193.     if (workp > work && workp[-1] == ' ')    /* Drop trailing blank    */
  194.         workp--;
  195.     *workp = EOS;                /* Terminate work    */
  196.     dp->repl = savestring(work);        /* Save the string    */
  197.     dp->nargs = nargs;            /* Save arg count    */
  198. #if DEBUG
  199.     if (debug)
  200.         dumpadef("macro definition", dp);
  201. #endif
  202.     if (isredefine) {            /* Error if redefined    */
  203.         if ((old != NULL && dp->repl != NULL && !streq(old, dp->repl))
  204.          || (old == NULL && dp->repl != NULL)
  205.          || (old != NULL && dp->repl == NULL)) {
  206.         cwarn("Redefining defined variable \"%s\"", dp->name);
  207.         }
  208.         if (old != NULL)            /* We don't need the    */
  209.         free(old);            /* old definition now.    */
  210.     }     
  211.     return(0);
  212.  
  213. bad_define:
  214.     cerror("#define syntax error", NULLST);
  215.     inmacro = FALSE;            /* Stop <newline> hack    */
  216. }
  217.  
  218. int
  219. checkparm(c, dp)
  220. register int    c;
  221. DEFBUF        *dp;
  222. /*
  223.  * Replace this param if it's defined, returning TRUE.
  224.  * Note that the macro name is a possible replacement token.
  225.  * We stuff DEF_MAGIC in front of the token
  226.  * which is treated as a LETTER by the token scanner and eaten by
  227.  * the output routine.  This prevents the macro expander from
  228.  * looping if someone writes "#define foo foo".
  229.  */
  230. {
  231.     register int        i;
  232.     register char        *cp;
  233.  
  234.     scanid(c);                /* Get parm to tokenbuf */
  235.     for (i = 0; i < nargs; i++) {        /* For each argument    */
  236.         if (streq(parlist[i], tokenbuf)) {    /* If it's known    */
  237.         save(i + MAC_PARM);            /* Save a magic cookie    */
  238.         return(TRUE);            /* And exit the search    */
  239.         }
  240.     }
  241.     if (streq(dp->name, tokenbuf))        /* Macro name in body?    */
  242.         save(DEF_MAGIC);            /* Save magic marker    */
  243.     for (cp = tokenbuf; *cp != EOS;)    /* And save        */
  244.         save(*cp++);            /* The token itself    */
  245.     return(FALSE);
  246. }
  247.  
  248. #if STRING_FORMAL
  249. stparmscan(delim, dp)
  250. int        delim;
  251. register DEFBUF    *dp;
  252. /*
  253.  * Scan the string (starting with the given delimiter).
  254.  * The token is replaced if it is the only text in this string or
  255.  * character constant.  The algorithm follows checkparm() above.
  256.  * Note that scanstring() has approved of the string.
  257.  */
  258. {
  259.     register int        c;
  260.  
  261.     /*
  262.      * Warning -- this code hasn't been tested for a while.
  263.      * It exists only to preserve compatibility with earlier
  264.      * implementations of cpp.  It is not part of the Draft
  265.      * ANSI Standard C language.
  266.      */
  267.     save(delim);
  268.     instring = TRUE;
  269.     while ((c = get()) != delim
  270.          && c != '\n'
  271.          && c != EOF_CHAR) {
  272.         if (type[c] == LET)            /* Maybe formal parm    */
  273.         checkparm(c, dp);
  274.         else {
  275.         save(c);
  276.         if (c == '\\')
  277.             save(get());
  278.         }
  279.     }
  280.     instring = FALSE;
  281.     if (c != delim)
  282.         cerror("Unterminated string in macro body", NULLST);
  283.     save(c);
  284. }
  285. #endif
  286.  
  287. doundef()
  288. /*
  289.  * Remove the symbol from the defined list.
  290.  * Called from the #control processor.
  291.  */
  292. {
  293.   register int c;
  294.  
  295.   if (type[(c = skipws())] != LET)
  296.     cerror("Illegal #undef argument", NULLST);
  297.   else
  298.     {
  299.       scanid(c);                /* Get name to tokenbuf */
  300.       defendel(tokenbuf, TRUE);
  301.     }
  302. }
  303.  
  304. textput(text)
  305. char        *text;
  306. /*
  307.  * Put the string in the parm[] buffer.
  308.  */
  309. {
  310.     register int    size;
  311.  
  312.     size = strlen(text) + 1;
  313.     if ((parmp + size) >= &parm[NPARMWORK])
  314.         cfatal("Macro work area overflow", NULLST);
  315.     else {
  316.         strcpy(parmp, text);
  317.         parmp += size;
  318.     }
  319. }
  320.  
  321. charput(c)
  322. register int    c;
  323. /*
  324.  * Put the byte in the parm[] buffer.
  325.  */
  326. {
  327.     if (parmp >= &parm[NPARMWORK])
  328.         cfatal("Macro work area overflow", NULLST);
  329.     else {
  330.         *parmp++ = c;
  331.     }
  332. }
  333.  
  334. /*
  335.  *        M a c r o   E x p a n s i o n
  336.  */
  337.  
  338. expand(tokenp)
  339. register DEFBUF    *tokenp;
  340. /*
  341.  * Expand a macro.  Called from the cpp mainline routine (via subroutine
  342.  * macroid()) when a token is found in the symbol table.  It calls
  343.  * expcollect() to parse actual parameters, checking for the correct number.
  344.  * It then creates a "file" containing a single line containing the
  345.  * macro with actual parameters inserted appropriately.  This is
  346.  * "pushed back" onto the input stream.  (When the get() routine runs
  347.  * off the end of the macro line, it will dismiss the macro itself.)
  348.  */
  349. {
  350.     register int        c;
  351.  
  352. #if DEBUG
  353.     if (debug)
  354.         dumpadef("expand entry", tokenp);
  355. #endif    
  356.     /*
  357.      * If no macro is pending, save the name of this macro
  358.      * for an eventual error message.
  359.      */
  360.     if (recursion++ == 0)
  361.         macro = tokenp;
  362.     else if (recursion == RECURSION_LIMIT) {
  363.         cerror("Recursive macro definition of \"%s\"", tokenp->name);
  364.         fprintf(stderr, "(Defined by \"%s\")\n", macro->name);
  365.         if (rec_recover) {
  366.         do {
  367.             c = get();
  368.         } while (infile != NULL && infile->fp == NULL);
  369.         unget();
  370.         recursion = 0;
  371.         return(0);
  372.         }
  373.     }
  374.     /*
  375.      * Here's a macro to expand.
  376.      */
  377.     nargs = 0;                /* Formals counter    */
  378.     parmp = parm;                /* Setup parm buffer    */
  379.     switch (tokenp->nargs) {
  380.     case DEF_BUILTIN:
  381.       (tokenp->expander)(tokenp->repl);    /* Builtin  macros      */
  382.       break;
  383.     default:
  384.         /*
  385.          * Nothing funny about this macro.
  386.          */
  387.         if (tokenp->nargs < 0)
  388.         cfatal("Bug: Illegal __ macro \"%s\"", tokenp->name);
  389.         while ((c = skipws()) == '\n')    /* Look for (, skipping    */
  390.         wrongline = TRUE;        /* spaces and newlines    */
  391.         if (c != '(') {
  392.         /*
  393.          * If the programmer writes
  394.          *    #define foo() ...
  395.          *    ...
  396.          *    foo [no ()]
  397.          * just write foo to the output stream.
  398.          */
  399.         unget();
  400.         cwarn("Macro \"%s\" needs arguments", tokenp->name);
  401.         fputs(tokenp->name, stdout);
  402.         return(0);
  403.         }
  404.         else if (expcollect()) {        /* Collect arguments    */
  405.         if (tokenp->nargs != nargs) {    /* Should be an error?    */
  406.             cwarn("Wrong number of macro arguments for \"%s\"",
  407.             tokenp->name);
  408.         }
  409. #if DEBUG
  410.         if (debug)
  411.             dumpparm("expand");
  412. #endif
  413.         }                /* Collect arguments        */
  414.     case DEF_NOARGS:        /* No parameters just stuffs    */
  415.         expstuff(tokenp);        /* Do actual parameters        */
  416.     }                /* nargs switch            */
  417. }
  418.  
  419. void
  420. expand_line (dp)
  421.   char* dp;
  422. {
  423.   register FILEINFO    *file;
  424.               /* Find bottom level file (the file being compiled) */
  425.   for (file = infile; file != NULL; file = file->parent) {
  426.     if (file->parent == NULL) {
  427.       sprintf(work, "%d", file->line);
  428.       ungetstring(work);
  429.       break;
  430.     }
  431.   }
  432. }
  433.  
  434. void
  435. expand_file (dp)
  436.      char *dp;
  437. {
  438.   register FILEINFO    *file;
  439.               /* Find bottom level file (the file being compiled) */
  440.   for (file = infile; file != NULL; file = file->parent) {
  441.     if (file->parent == NULL) {
  442.       sprintf(work, "\"%s\"", (file->progname != NULL)
  443.           ? file->progname : file->filename);
  444.       ungetstring(work);
  445.       break;
  446.     }
  447.   }
  448. }
  449.  
  450. #ifndef COOL
  451. /* We need this routine here only when we are building a clean, ie. non-COOL
  452.  * preprocessor. For COOL, this function is defined in cpp7.c
  453.  */
  454. FILEINFO*
  455. get_temp_file (bufsize, name)
  456.      int bufsize;
  457.      char* name;
  458. {
  459.   extern FILEINFO    *getfile();
  460.   FILEINFO* file = getfile(bufsize, name);
  461.   infile = file->parent;
  462.   file->parent = NULL;
  463.   line = infile->line;
  464.   return(file);
  465. }
  466. #endif
  467.  
  468. FILE_LOCAL int
  469. expcollect()
  470. /*
  471.  * Collect the actual parameters for this macro.  TRUE if ok.
  472.  */
  473. {
  474.     register int    c;
  475.     register int    paren;            /* For embedded ()'s    */
  476.     extern int    charput();
  477.  
  478.     for (;;) {
  479.         paren = 0;                /* Collect next arg.    */
  480.         while ((c = skipws()) == '\n')    /* Skip over whitespace    */
  481.         wrongline = TRUE;        /* and newlines.    */
  482.         if (c == ')') {            /* At end of all args?    */
  483.         /*
  484.          * Note that there is a guard byte in parm[]
  485.          * so we don't have to check for overflow here.
  486.          */
  487.         *parmp = EOS;            /* Make sure terminated    */
  488.         break;                /* Exit collection loop    */
  489.         }
  490.         else if (nargs >= LASTPARM)
  491.         cfatal("Too many arguments in macro expansion", NULLST);
  492.         parlist[nargs++] = parmp;        /* At start of new arg    */
  493.         for (;; c = cget()) {        /* Collect arg's bytes    */
  494.         if (c == EOF_CHAR) {
  495.             cfatal("end of file within macro argument", NULLST);
  496.             return (FALSE);        /* Sorry.        */
  497.         }
  498.         else if (c == '\\') {        /* Quote next character    */
  499.             charput(c);            /* Save the \ for later    */
  500.             charput(cget());        /* Save the next char.    */
  501.             continue;            /* And go get another    */
  502.         }
  503.         else if (type[c] == QUO) {    /* Start of string?    */
  504.             scanstring(c, charput);    /* Scan it off        */
  505.             continue;            /* Go get next char    */
  506.         }
  507.         else if (c == '(')        /* Worry about balance    */
  508.             paren++;            /* To know about commas    */
  509.         else if (c == ')') {        /* Other side too    */
  510.             if (paren == 0) {        /* At the end?        */
  511.             unget();        /* Look at it later    */
  512.             break;            /* Exit arg getter.    */
  513.             }
  514.             paren--;            /* More to come.    */
  515.         }
  516.         else if (c == ',' && paren == 0) /* Comma delimits args    */
  517.             break;
  518.         else if (c == '\n')        /* Newline inside arg?    */
  519.             wrongline = TRUE;        /* We'll need a #line    */
  520.         charput(c);            /* Store this one    */
  521.         }                    /* Collect an argument    */
  522.         charput(EOS);            /* Terminate argument    */
  523. #if DEBUG
  524.         if (debug)
  525.             printf("parm[%d] = \"%s\"\n", nargs, parlist[nargs - 1]);
  526. #endif
  527.     }                    /* Collect all args.    */
  528.     return (TRUE);                /* Normal return    */
  529. }
  530.  
  531. FILE_LOCAL
  532. expstuff(tokenp)
  533. DEFBUF        *tokenp;        /* Current macro being expanded    */
  534. /*
  535.  * Stuff the macro body, replacing formal parameters by actual parameters.
  536.  */
  537. {
  538.     register int    c;            /* Current character    */
  539.     register char    *inp;            /* -> repl string    */
  540.     register char    *defp;            /* -> macro output buff    */
  541.     int        size;            /* Actual parm. size    */
  542.     char        *defend;        /* -> output buff end    */
  543.     int        string_magic;        /* String formal hack    */
  544.     FILEINFO    *file;                /* Funny #include    */
  545.     extern FILEINFO    *getfile();
  546.     extern FILEINFO    *get_temp_file();
  547.  
  548.     file = getfile(NBUFF, tokenp->name);
  549.     inp = tokenp->repl;            /* -> macro replacement    */
  550.     defp = file->buffer;            /* -> output buffer    */
  551.     defend = defp + (NBUFF - 24);        /* Note its end        */
  552.     if (inp != NULL) {
  553.         while ((c = (*inp++ & 0xFF)) != EOS) {
  554.           if (defp >= defend) {        /* If out of space      */
  555.         FILEINFO* new = get_temp_file(NBUFF, file->filename);
  556.         new->parent = file->parent; /* When new ends read from infile */
  557.         file->parent = new;        /* When file ends read from new   */
  558.         file = new;
  559.         *defp = EOS;
  560.         defp = file->buffer;
  561.         defend = defp + (NBUFF - 24);
  562.           }
  563.  
  564.           if (c >= MAC_PARM && c <= (MAC_PARM + PAR_MAC)) {
  565.         string_magic = (c == (MAC_PARM + PAR_MAC));
  566.         if (string_magic) {        /* When quoted parameter */
  567.           c = (*inp++ & 0xFF);
  568.           *defp++ = '\"';
  569.         }
  570.         /*
  571.          * Replace formal parameter by actual parameter string.
  572.          */
  573.         if ((c -= MAC_PARM) < nargs) {
  574.           size = strlen(parlist[c]);
  575.           if ((defp + size + 24) >= defend) {
  576.             *defp = EOS;        /* If out of space */
  577.             defend = defp;
  578.             if (string_magic) inp--; 
  579.             inp--;            /* backup and try again */
  580.             continue;
  581.           }
  582.           if (string_magic) {        /* When quoted parameter */
  583.             char* p = parlist[c];
  584.             for(; (c = *p++) != EOS;) {
  585.               switch (c) {
  586.               case '\"':
  587.               case '\\':
  588.             *defp++ = '\\';
  589.               default:
  590.             *defp++ = c;
  591.               } /* switch */
  592.             } /* for */
  593.             *defp++ = '\"';
  594.           } else {
  595.             strncpy(defp, parlist[c], size);
  596.             defp += size;
  597.           } /* if string_magic */
  598.         } /* if valid parm */
  599.           } /* if parm */
  600.           else if (c != DEF_MAGIC)
  601.         *defp++ = c;
  602.         }
  603.       }
  604.     *defp = EOS;
  605. #if DEBUG
  606.     if (debug > 1)
  607.         printf("macroline: \"%s\"\n", file->buffer);
  608. #endif
  609. }
  610.  
  611. #if DEBUG
  612. dumpparm(why)
  613. char        *why;
  614. /*
  615.  * Dump parameter list.
  616.  */
  617. {
  618.     register int    i;
  619.  
  620.     printf("dump of %d parameters (%d bytes total) %s\n",
  621.         nargs, parmp - parm, why);
  622.     for (i = 0; i < nargs; i++) {
  623.         printf("parm[%d] (%d) = \"%s\"\n",
  624.         i + 1, strlen(parlist[i]), parlist[i]);
  625.     }
  626. }
  627. #endif
  628.